var CANVAS_WIDTH = 1000;//画布宽度
var CANVAS_HEIGHT = 1000;

var frame = 0;
var total_frame = 10;

const heart_colors = ["#A52A2A","#7FFF00","#DC143C","#00FFFF","#FF00FF","#FFD700","#4B0082"];
const point_colors = ["#ff1943", "#ff1943", "#ff1943"];

window.onload = function(){
    CANVAS_WIDTH = document.documentElement.clientWidth;
    CANVAS_HEIGHT = document.documentElement.clientHeight;

    var canvas = document.getElementById("canvas");
    canvas.width = CANVAS_WIDTH;
    canvas.height = CANVAS_HEIGHT;

    var context = canvas.getContext("2d");
    var hearts = calc_heart_data();
    var datas = calc_main_data();
    console.log(datas);

    setInterval( function(){
        render( context, datas, hearts );
    }, 300 );
}

function render(context, datas, hearts) {
    context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT );
    frame = frame >= total_frame ? 0 : frame;
    for (var i = 0; i < hearts[0].length; i++) {
        var s = hearts[0][i].s;
        if (i % 2 == 0) {
            s *= Math.sin(frame/total_frame * Math.PI)
        } else {
            s *= Math.cos(frame/total_frame * Math.PI)
        }
        s = Math.abs(s);
        draw_heart(context, s, hearts[0][i].x, hearts[0][i].y, i);
    }
    for (var i = 0; i < datas[frame].length; i++) {
        draw_point(context, datas[frame][i].x, datas[frame][i].y, 2);
    }
    frame = frame + 1;
}

function calc_heart_data() {
    var datas = [];

    var num = 300 + Math.random() * 30;
    for (var j = 0; j < 1; j++ ) {
        var data = [];
        for (var i = 0; i < num; i++) {
            var s = Math.abs(Math.random() - 0.1);
            var x = CANVAS_WIDTH/2 +  (Math.random() - 0.5) * 2 * CANVAS_WIDTH/2
            var y = CANVAS_HEIGHT/2 +  (Math.random() - 0.5) * 2 * CANVAS_HEIGHT/2
            data.push({x: x, y: y, s: s});
        }
        datas[j] = data;
    }

    return datas;
}

function calc_main_data(){

    var all_points = []

    // 原始数据
    for (var i = 0; i < 2000; i++){
        var t = Math.random() * 2 * Math.PI;
        var a = heart_function(t, 20);
        all_points.push(a);
    }

    // 内扩散
    var points_inner = [];
    for (var j = 0; j < 2; j++) {
        for (var i = 0; i < all_points.length; i++) {
            var a = scatter_inside(all_points[i].x, all_points[i].y, 0.03);
            points_inner.push(a);
        }
    }

     // 内扩散
     var points_center = [];
     for (var j = 0; j < 3000; j++) {
         var i = Math.ceil(Math.random() * (all_points.length - 1));
         var a = scatter_inside(all_points[i].x, all_points[i].y, 0.07);
         points_center.push(a);
     }

     var points = {};
     for (var frame = 0; frame < total_frame; frame++) {
        var scale = 10 * curve(frame / 10 * Math.PI);
        var ratio = 4 + 6 * (1+ scale);
        var num = 2000 + 100 * Math.abs(scale * scale);

        // 光环
        var datas = [];
        for (var i = 0; i< num; i++) {
            var t = Math.random() * 2 * Math.PI;
            var a = heart_function(t, 20.9);
            var b = calc_pos(a.x, a.y, ratio);
            var x = b.x + (Math.random() - 0.5) * 24;
            var y = b.y + (Math.random() - 0.5) * 24;
            datas.push({x: x, y: y});
        }

        // 轮廓
        for (var i = 0; i < all_points.length; i++) {
            var a = calc_pos(all_points[i].x, all_points[i].y, ratio);
            datas.push({x: a.x, y: a.y});
        }

        // 内部
        for (var i = 0; i < points_inner.length; i++) {
            var a = calc_pos(points_inner[i].x, points_inner[i].y, ratio);
            datas.push({x: a.x, y: a.y});
        }

        // 中心
        for (var i = 0; i < points_center.length; i++) {
            var a = calc_pos(points_center[i].x, points_center[i].y, ratio);
            datas.push({x: a.x, y: a.y});
        }

        points[frame] = datas;
     }

     return points;
}

// detal 最大值是5 最小值是0
function gen_heart_poin(count, detal, rand_type, abs, beta) {
    var points = [];
    for (var i = -6; i < 6 ; i += 12 / count) {
        var x = (16 * Math.pow(Math.sin(i), 3));
        var y = (13 * Math.cos(i) - 5 * Math.cos(2*i) - 2 * Math.cos(3 * i) - Math.cos(4 * i)) * -1;
        
        if (rand_type == "unin") {
            // 均匀分布
            var d1 = (Math.random() - 0.5) * detal;
            var d2 = (Math.random() - 0.5) * detal;
        } if (rand_type == "log") {
            var d1 = -1 * beta * Math.log(Math.random());
            var d2 = -1 * beta * Math.log(Math.random());
        } else {
            // 正态分布
            var d1 = normalRandom(0, 0.5) * detal;
            var d2 = normalRandom(0, 0.5) * detal;
        }

        if (abs) {
            d1 = Math.abs(d1);
            d2 = Math.abs(d2);
        }
        
        if (x > 0) {
            x = x - d1;
        } else {
            x = x + d1;
        }

        if (y > 0) {
            y = y - d2;
        } else {
            y = y + d2;
        }

        points.push({x: x, y: y});
    }
    console.log(points);
    return points;
}

function calc_pos(x, y, ratio) {
    force = Math.pow(
        Math.pow(
            Math.pow(x - CANVAS_WIDTH/2, 2) + Math.pow(y - CANVAS_HEIGHT/2, 2), 
        0.52), 
    -1);
    dx = ratio * force * (x - CANVAS_WIDTH/2) + (Math.random() - 0.5) * 2;
    dy = ratio * force * (y - CANVAS_HEIGHT/2) + (Math.random() - 0.5) * 2;
    return {x: x - dx, y: y - dy}
}

// 抖动
function shrink(x, y, ratio) {
    force = -1 * Math.pow(
        Math.pow(
            Math.pow(x - CANVAS_WIDTH/2, 2) + Math.pow(y - CANVAS_HEIGHT/2, 2), 
        0.6), 
    -1);
    dx = ratio * force * (x - CANVAS_WIDTH/2);
    dy = ratio * force * (y - CANVAS_HEIGHT/2);
    return {x: x - dx, y: y - dy}
}

// 随机内部扩散
function scatter_inside(x, y, beta) {
    ratio_x = - beta * Math.log(Math.random())
    ratio_y = - beta * Math.log(Math.random())
    dx = ratio_x * (x - CANVAS_WIDTH/2)
    dy = ratio_y * (y - CANVAS_HEIGHT/2)
    return {x: x - dx, y: y - dy}
}

// 爱心函数生成器
function heart_function(i, ratio = 20) {
    var x = (16 * Math.pow(Math.sin(i), 3));
    var y = (13 * Math.cos(i) - 5 * Math.cos(2*i) - 2 * Math.cos(3 * i) - Math.cos(4 * i)) * -1;
    x *= ratio;
    y *= ratio;
    x += CANVAS_WIDTH/2;
    y += CANVAS_HEIGHT/2;
    return {x: x, y: y}
}

function draw_heart(context, scale, x_padding, y_padding, idx) {
    context.fillStyle = heart_colors[Math.ceil(idx % heart_colors.length)];
    context.beginPath();
    for (var i = -6; i < 6 ; i += 0.01) {
        var x = (16 * Math.pow(Math.sin(i), 3));
        var y = (13 * Math.cos(i) - 5 * Math.cos(2*i) - 2 * Math.cos(3 * i) - Math.cos(4 * i)) * -1;
        x = x * scale;
        y = y * scale;
        context.lineTo(x + x_padding, y + y_padding) ;
    }
    context.fill();
}

function draw_point(context, x, y, redius) {
    context.fillStyle = point_colors[Math.ceil(Math.random() * point_colors.length)];
    context.beginPath();
    context.arc(x - redius/2, y, redius/2, redius, 2*Math.PI, false);
    context.fill();
}

function curve(p) {
    return 2 * (2 * Math.sin(4 * p)) / (2 * Math.PI);
}

function normalRandom(mean, std) {
    let u = 0.0, v = 0.0, w = 0.0, c = 0.0;
    do {
        //获得两个（-1,1）的独立随机变量
        u = Math.random() * 2 - 1.0;
        v = Math.random() * 2 - 1.0;
        w = u * u + v * v;
    } while (w == 0.0 || w >= 1.0)
    //Box-Muller转换
    c = Math.sqrt((-2 * Math.log(w)) / w);
    let normal = mean + (u * c) * std;
    return normal;
}
